package com.index.search;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.index.pojo.Product;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.transport.InetSocketTransportAddress;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.transport.client.PreBuiltTransportClient;

import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;

/**
 * 增删改
 */
public class IndexManagerService {

    //当返现一段代码出现超过两次时 就要考虑抽取代码了
    public TransportClient getTransportClient() throws UnknownHostException {
        //1 : 配置集群的名字，EMPTY不写， 默认是：'elasticsearch'
        Settings settings = Settings.EMPTY;

        //连接的集群不是默认名
        /* Settings settings = Settings.builder().put("cluster.name","cluster-es")
                //.put("number_of_shards",10)    //设置分片数量
                //.put("number_of_replicas",2)  //设置备份多少份
                .build();*/

        //2： 建立TransportClient 对象完成对es服务调用 配置es服务的ip和端口  与ElasticSearch服务器的数据传
        // 输（即检索与创建）的客户端
        TransportClient transportClient = new PreBuiltTransportClient(settings);

        //3：通过传输客户端添加服务器信息  : es服务器的IP 与 端口 端口是9300 通过协议去连接的 使用的端口是9300
        transportClient.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("127.0.0.1"), 9300));
        //使用集群的时候，各个es服务器的地址都需要指定
        //transportClient.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("127.0.0.1"),9301));
        //transportClient.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("127.0.0.1"),9302));

        //返回
        return transportClient;
    }

    //创建索引方式二
    public void createIndex() throws IOException {
        //1-3 已抽取

        //4：创建索引文档 ---es是基于json数据传输
        /*
         * elasticSearch 进行索引库的增删改查的url是restful风格的 传输的数据是json格式 {id:1,name:"xxx",age:"234234"}
         * 即最终我们设置的数据都会拼接成下面这个样子：已添加document为例：
         * url:  http://127.0.0.1:9200/blog/article/4
         * body:{
                    "id":4,
                    "title":"叫你XX你不XX，你XX",
                    "content":"叫你XX你不XX，你XX叫你XX你不XX，你XX叫你XX你不XX，你XX"
                }
         * */
        XContentBuilder contentBuilder = XContentFactory.jsonBuilder().startObject()
                .field("id", 3)
                .field("title", "elasticsearch是一个基于lucene的搜索服务")
                .field("content", "ElasticSearch是一个基于Lucene的搜索服务器。" +
                        "它提供了一个分布式多用户能力的全文搜索引擎，基于RESTful web接口。" +
                        "Elasticsearch是用Java开发的，并作为Apache许可条款下的开放源码发布，" +
                        "是当前流行的企业级搜索引擎。设计用于云计算中，能够达到实时搜索，稳定，" +
                        "可靠，快速，安装使用方便。")
                .endObject();

        // 5:创建索引库 指定索引库的名字 以及表的名字
//        IndexResponse response = getTransportClient().prepareIndex("blog", "article").setSource(contentBuilder).get();
        //还可以指定document的id哦 不指定也可以 会生成一个随机的id 注意：删除document时 要用这个id去删除
        IndexResponse response = getTransportClient().prepareIndex("hyh_blog", "article", "4").setSource(contentBuilder).get();
        //IndexResponse response = getTransportClient().prepareIndex("blog", "article", "3").setSource(contentBuilder).get();
        //打印结果
        System.out.println(response.status());

        // 6:释放资源
        getTransportClient().close();
    }

    //创建索引方式一
    public void createIndexByObject() throws IOException {
        //1-3 已抽取

        //4：创建索引文档 ---es是基于json数据传输
        /*
         * elasticSearch 进行索引库的增删改查的url是restful风格的 传输的数据是json格式 {id:1,name:"xxx",age:"234234"}
         * */
        Product product = new Product();
        product.setId(2);
        product.setTitle("习近平将出席二十国集团领导人第十四次峰会");
        product.setContent("ElasticSearch是一个基于Lucene的搜索服务器。\" +\n" +
                "                        \"它提供了一个分布式多用户能力的全文搜索引擎，基于RESTful web接口。\" +\n" +
                "                        \"Elasticsearch是用Java开发的，并作为Apache许可条款下的开放源码发布，\" +\n" +
                "                        \"是当前流行的企业级搜索引擎。设计用于云计算中，能够达到实时搜索，稳定，\" +\n" +
                "                        \"可靠，快速，安装使用方便。");

        ObjectMapper objectMapper = new ObjectMapper();
        String productJson = objectMapper.writeValueAsString(product);

        // 5:创建索引库 指定索引库的名字 以及表的名字
        IndexResponse response = getTransportClient().prepareIndex("blog", "article").setSource(productJson).get();
        //打印结果
        System.out.println(response.status());   //create

        // 6:释放资源
        getTransportClient().close();
    }


    //修改document：注意：修改与添加document的代码一毛一样，即第二次运行添加操作，就时修改
    //即只要document的id相同，再次运行就是修改
    public void updateIndex() throws IOException {
        //1-3 已抽取

        //4：创建 or 修改索引文档 ---es是基于json数据传输
        /*
         * elasticSearch 进行索引库的增删改查的url是restful风格的 传输的数据是json格式 {id:1,name:"xxx",age:"234234"}
         * */
        Product product = new Product();
        product.setId(2);
        product.setTitle("习近平将出席二十国集团领导人第十四次峰会--update");

        //没有 就覆盖为null
        /*product.setContent("ElasticSearch是一个基于Lucene的搜索服务器。\" +\n" +
                "                        \"它提供了一个分布式多用户能力的全文搜索引擎，基于RESTful web接口。\" +\n" +
                "                        \"Elasticsearch是用Java开发的，并作为Apache许可条款下的开放源码发布，\" +\n" +
                "                        \"是当前流行的企业级搜索引擎。设计用于云计算中，能够达到实时搜索，稳定，\" +\n" +
                "                        \"可靠，快速，安装使用方便。");*/

        ObjectMapper objectMapper = new ObjectMapper();
        String productJson = objectMapper.writeValueAsString(product);

        // 5:创建 or 修改索引库 指定索引库的名字 以及表的名字
        //只要document的id相同，再次运行就是修改
        IndexResponse response = getTransportClient().prepareIndex("blog", "article", "AWuECWtgfcqMpk7eV-a9").setSource(productJson).get();
        //打印结果
        System.out.println(response.status());  //ok

        // 6:释放资源
        getTransportClient().close();
    }


    //删除索引：注意：是根据document的id去删除
    public void deleteIndex() throws Exception {
        //第一种方式（都要指索引 制动表 指定文档id）
        // index 索引库  type 类型（表） id:一定是文档ID
        DeleteResponse response = getTransportClient().delete(new DeleteRequest("blog", "article", "4")).get();

        //第二种方式（都要指索引 制动表 指定文档id）
        //DeleteResponse response =  getTransportClient().prepareDelete("blog","content","3").get();
        System.out.println(response.status());

        //释放资源
        getTransportClient().close();
    }


    //创建映射
    // 注意一定要在创建索引库之后再去在设置mapping 创建mapping是一次性的，因为可以理解是定义表结构
    public void createMapping() throws IOException {
        //索引定义
        XContentBuilder contentBuilder = XContentFactory.jsonBuilder()
                .startObject()   //指mappings
                .startObject("article")  //指表
                .startObject("properties")  //指属性
                .startObject("id").field("type", "long").field("store", true).endObject()
                .startObject("title").field("type", "text").field("store", true).field("analyzer", "ik_smart").endObject()
                .startObject("content").field("type", "text").field("store", true).field("analyzer", "ik_smart").endObject()
                .endObject()
                .endObject()
                .endObject();

        //设置要做映射的索引与type
        getTransportClient().admin().indices()
                // 设置要做映射的索引
                .preparePutMapping("hyh_blog")
                // 设置做映射的type
                .setType("article")
                // 设置mapping信息，可以是XContentBuilder 也可以是json字符串
                .setSource(contentBuilder).get();

        //5:关闭
        getTransportClient().close();
    }
}
